// --------------------------------------------------------------------------------------------------------------------
// <copyright file="LiveObjectContainerManager.cs" company="Open Trader">
//   Copyright (c) David Denis (david.denis@systemathics.com)
// </copyright>
// <summary>
//   |  Open Trader - The Open Source Systematic Trading Platform
//   |
//   |  This program is free software: you can redistribute it and/or modify
//   |  it under the terms of the GNU General Public License as published by
//   |  the Free Software Foundation, either version 2 of the License, or
//   |  (at your option) any later version.
//   |
//   |  This program is distributed in the hope that it will be useful,
//   |  but WITHOUT ANY WARRANTY; without even the implied warranty of
//   |  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   |  GNU General Public License for more details.
//   |
//   |  You should have received a copy of the GNU General Public License
//   |  along with this program.  If not, see http://www.gnu.org/licenses
//   |
//   |  Up to date informations about Open Trader can be found at :
//   |    http://opentrader.org
//   |    http://opentrader.codeplex.com
//   |
//   |  For professional services, please visit us at :
//   |    http://www.systemathics.com
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Org.OpenTrader.Framework.LiveObjects
{
    #region Using Directives

    using Org.OpenTrader.Framework.LiveObjects.Interfaces;

    #endregion

    /// <summary>
    /// The live object container manager.
    /// </summary>
    public abstract class LiveObjectContainerManager : ILiveObjectContainerManager
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="LiveObjectContainerManager"/> class.
        /// </summary>
        /// <param name="desc">
        /// The desc.
        /// </param>
        public LiveObjectContainerManager(ILiveObjectContainerDescriptor desc)
        {
            this.Descriptor = desc;
        }

        #region ILiveObjectContainerManager Members

        /// <summary>
        /// Gets or sets Resources.
        /// </summary>
        public IResource[] Resources { get; set; }

        /// <summary>
        /// Gets or sets Container.
        /// </summary>
        public ILiveObjectContainer Container { get; set; }

        /// <summary>
        /// Gets or sets Descriptor.
        /// </summary>
        public ILiveObjectContainerDescriptor Descriptor { get; set; }

        /// <summary>
        /// The create container.
        /// </summary>
        /// <returns>
        /// The create container.
        /// </returns>
        public abstract bool CreateContainer();

        /// <summary>
        /// The destroy container.
        /// </summary>
        /// <returns>
        /// The destroy container.
        /// </returns>
        public abstract bool DestroyContainer();

        #endregion

#if BENCHMARKS

        public void BenchmarkContainer()
        {
            if (Container == null)
                return;

            Stdout.WriteLine(string.Format("Benchmarking container {0} ({1})" , Container.Descriptor.ID, GetType().Name));

            BenchmarkCalls(Container);
            BenchmarkXfer(Container);

            Stdout.WriteLine();
        }

        private static void BenchmarkCalls(ILiveObjectContainer c)
        {
            Stdout.WriteLine("  Latency");

            const int count = 1000;
            RollingTimeserie t = new RollingTimeserie(count);
            var T1 = Timings.Now;
            for (int i = 0; i < count; i++)
            {
                var t1 = Timings.Now;
                c.BenchmarkingVoidVoid();
                var t2 = Timings.Now;
                var dt = t2 - t1;
                t.Add((decimal)dt.TotalMilliseconds);
            }

            var T2 = Timings.Now;
            var dT = T2 - T1;
            Stdout.WriteLine("    After {0} calls to void BenchmarkingVoidVoid()", count);
            Stdout.WriteLine("      Per call E={0}ms V={1}", t.Expectancy(), t.Var());
            Stdout.WriteLine("      Total time {0}ms", dT.TotalMilliseconds);
        }

        private static void BenchmarkXfer(ILiveObjectContainer c)
        {
            Stdout.WriteLine("  Xfer");

            const int count = 1000;
            var T1 = Timings.Now;
            RollingTimeserie t = new RollingTimeserie(count);
            byte[] data = null;
            for (int i = 0; i < count; i++)
            {
                var t1 = Timings.Now;
                data = c.Benchmarking1KBVoid();
                var t2 = Timings.Now;
                var dt = t2 - t1;
                t.Add((decimal)dt.TotalMilliseconds);
            }

            var T2 = Timings.Now;
            var dT = T2 - T1;

            var xfer = (count) / dT.TotalSeconds;
            Stdout.WriteLine("    After {0} calls to byte [] Benchmarking1KBVoid", 
                count );
            Stdout.WriteLine("      Per call E={0}ms V={1}", t.Expectancy(), t.Var());
            Stdout.WriteLine("      Total time {0}ms", dT.TotalMilliseconds);
            Stdout.WriteLine("      Xfer rate={0}MBytes/sec", xfer);
        }

#endif
    }
}